// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//
#include <pollux/expression/special_form_registry.h>
#include <pollux/functions/lib/re2_functions.h>
#include <pollux/functions/prestosql/string_functions.h>
#include <pollux/functions/prestosql/url_functions.h>
#include <pollux/functions/sparksql/concat_ws.h>
#include <pollux/functions/sparksql/mask_function.h>
#include <pollux/functions/sparksql/split.h>
#include <pollux/functions/sparksql/string.h>
#include <pollux/functions/sparksql/string_to_map.h>

namespace kumo::pollux::functions {
    void registerSparkStringFunctions(const std::string &prefix) {
        POLLUX_REGISTER_VECTOR_FUNCTION(udf_concat, prefix + "concat");
        POLLUX_REGISTER_VECTOR_FUNCTION(udf_lower, prefix + "lower");
        POLLUX_REGISTER_VECTOR_FUNCTION(udf_upper, prefix + "upper");
        POLLUX_REGISTER_VECTOR_FUNCTION(udf_reverse, prefix + "reverse");
    }

    namespace sparksql {
        void registerStringFunctions(const std::string &prefix) {
            registerSparkStringFunctions(prefix);
            register_function<StartsWithFunction, bool, Varchar, Varchar>(
                {prefix + "startswith"});
            register_function<EndsWithFunction, bool, Varchar, Varchar>(
                {prefix + "endswith"});
            register_function<ContainsFunction, bool, Varchar, Varchar>(
                {prefix + "contains"});
            register_function<LocateFunction, int32_t, Varchar, Varchar, int32_t>(
                {prefix + "locate"});
            register_function<TrimSpaceFunction, Varchar, Varchar>({prefix + "trim"});
            register_function<TrimFunction, Varchar, Varchar, Varchar>({prefix + "trim"});
            register_function<LTrimSpaceFunction, Varchar, Varchar>({prefix + "ltrim"});
            register_function<LTrimFunction, Varchar, Varchar, Varchar>(
                {prefix + "ltrim"});
            register_function<RTrimSpaceFunction, Varchar, Varchar>({prefix + "rtrim"});
            register_function<RTrimFunction, Varchar, Varchar, Varchar>(
                {prefix + "rtrim"});
            register_function<TranslateFunction, Varchar, Varchar, Varchar, Varchar>(
                {prefix + "translate"});
            register_function<ConvFunction, Varchar, Varchar, int32_t, int32_t>(
                {prefix + "conv"});
            register_function<ReplaceFunction, Varchar, Varchar, Varchar>(
                {prefix + "replace"});
            register_function<ReplaceFunction, Varchar, Varchar, Varchar, Varchar>(
                {prefix + "replace"});
            register_function<FindInSetFunction, int32_t, Varchar, Varchar>(
                {prefix + "find_in_set"});
            register_function<UrlEncodeFunction, Varchar, Varchar>(
                {prefix + "url_encode"});
            register_function<UrlDecodeFunction, Varchar, Varchar>(
                {prefix + "url_decode"});
            register_function<sparksql::ChrFunction, Varchar, int64_t>({prefix + "chr"});
            register_function<AsciiFunction, int32_t, Varchar>({prefix + "ascii"});
            register_function<sparksql::LPadFunction, Varchar, Varchar, int32_t, Varchar>(
                {prefix + "lpad"});
            register_function<sparksql::RPadFunction, Varchar, Varchar, int32_t, Varchar>(
                {prefix + "rpad"});
            register_function<sparksql::LPadFunction, Varchar, Varchar, int32_t>(
                {prefix + "lpad"});
            register_function<sparksql::RPadFunction, Varchar, Varchar, int32_t>(
                {prefix + "rpad"});
            register_function<sparksql::SubstrFunction, Varchar, Varchar, int32_t>(
                {prefix + "substring"});
            register_function<
                sparksql::SubstrFunction,
                Varchar,
                Varchar,
                int32_t,
                int32_t>({prefix + "substring"});
            register_function<
                sparksql::OverlayVarcharFunction,
                Varchar,
                Varchar,
                Varchar,
                int32_t,
                int32_t>({prefix + "overlay"});
            register_function<
                sparksql::OverlayVarbinaryFunction,
                Varbinary,
                Varbinary,
                Varbinary,
                int32_t,
                int32_t>({prefix + "overlay"});
            register_function<
                sparksql::StringToMapFunction,
                Map<Varchar, Varchar>,
                Varchar,
                Varchar,
                Varchar>({prefix + "str_to_map"});
            register_function<sparksql::LeftFunction, Varchar, Varchar, int32_t>(
                {prefix + "left"});
            register_function<sparksql::BitLengthFunction, int32_t, Varchar>(
                {prefix + "bit_length"});
            register_function<sparksql::BitLengthFunction, int32_t, Varbinary>(
                {prefix + "bit_length"});
            exec::registerStatefulVectorFunction(
                prefix + "instr", instrSignatures(), makeInstr);
            exec::registerStatefulVectorFunction(
                prefix + "length", lengthSignatures(), makeLength);
            register_function<SubstringIndexFunction, Varchar, Varchar, Varchar, int32_t>(
                {prefix + "substring_index"});
            register_function<Empty2NullFunction, Varchar, Varchar>(
                {prefix + "empty2null"});
            register_function<
                LevenshteinDistanceFunction,
                int32_t,
                Varchar,
                Varchar,
                int32_t>({prefix + "levenshtein"});
            register_function<LevenshteinDistanceFunction, int32_t, Varchar, Varchar>(
                {prefix + "levenshtein"});
            register_function<RepeatFunction, Varchar, Varchar, int32_t>(
                {prefix + "repeat"});
            register_function<SoundexFunction, Varchar, Varchar>({prefix + "soundex"});
            register_function<Split, Array<Varchar>, Varchar, Varchar>({prefix + "split"});
            register_function<Split, Array<Varchar>, Varchar, Varchar, int32_t>(
                {prefix + "split"});
            register_function<MaskFunction, Varchar, Varchar>({prefix + "mask"});
            register_function<MaskFunction, Varchar, Varchar, Varchar>({prefix + "mask"});
            register_function<MaskFunction, Varchar, Varchar, Varchar, Varchar>(
                {prefix + "mask"});
            register_function<MaskFunction, Varchar, Varchar, Varchar, Varchar, Varchar>(
                {prefix + "mask"});
            register_function<
                MaskFunction,
                Varchar,
                Varchar,
                Varchar,
                Varchar,
                Varchar,
                Varchar>({prefix + "mask"});
            registerFunctionCallToSpecialForm(
                ConcatWsCallToSpecialForm::kConcatWs,
                std::make_unique<ConcatWsCallToSpecialForm>());
        }
    } // namespace sparksql
} // namespace kumo::pollux::functions
